/*
 * PVP.cpp
 *
 *  Created on: 2014. 3. 21.
 *      Author: mega
 */

#include "PVP.h"

#include "../../macro.h"
#include "../../User.h"
#include "../../engine.h"

#include "../../NLogic/Battle.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Monster.h"
#include "../../NLogic/Status.h"
#include "../../NLogic/Party.h"

#include "../../NResource/Static.h"
#include "../../NResource/ValidResource.h"

namespace ProjectZ { namespace NProcess { namespace NCombat {

PVP::PVP() {
	// TODO Auto-generated constructor stub
}

PVP::~PVP() {
	// TODO Auto-generated destructor stub
}

void
PVP::Attack(User * pUser, ::Network::Packet * pPacket)
{
	/*
	 * // 던전에서 공격
		CN_ATTACK_DUNGEON	0x0515
		{
			u8	u8effect;		// 데미지 이펙트 출력 여부(0 없음 , 1 있음)
			u32	damage_value;	// Damage value(0 : 공격 실패, 0보다 큰경우 공격 성공)
			u32	defender_gid;	// DEFENDER GID
			u8	defender_ismonster;	// DEFENDER의 몬스터여부(0:주인공 1:몬스터)
			u16	degree;			방향 벡터(보고있는 방향 0 : RIGHT, 90 : DOWN..)
			u8	statetype;		// 상태이상여부 상위 4bit / 백어택여부 하위4bit
			u8	ismonster;		// 공격자의 몬스터여부 (0 : 주인공 1: 몬스터)
			u32	attacker_gid;	// 공격자 GID
		}

		SN_ATTACK_DUNGEON	0x0516
		{
			u8	u8effect;		// 데미지 이펙트 출력 여부(0 없음 , 1 있음)
			u32	damage_value;	// Damage value(0 : 공격 실패, 0보다 큰경우 공격 성공)
			u32	defender_gid;	// DEFENDER GID
			u8	defender_ismonster;	// DEFENDER의 몬스터여부(0:주인공 1:몬스터)
			u32	defender_hp;	// DEFENDER의 데미지 반영 후 HP
			u16	degree;			방향 벡터(보고있는 방향 0 : RIGHT, 90 : DOWN..)
			u8	ismonster;		// 공격자의 몬스터여부 (0 : 주인공 1: 몬스터)
			u32	attacker_gid;	// 공격자 GID
		}
	 */

	Value clsValue;

	*pPacket >> clsValue.effect >> clsValue.damage_value >> clsValue.defender_gid;
	*pPacket >> clsValue.defender_ismonster >> clsValue.degree >> clsValue.statetype;
	*pPacket >> clsValue.ismonster >> clsValue.attacker_gid >> clsValue.attack_type;

	NResource::ValidResource::Flyweight * pFly = NResource::Static::Instance().GetValid()->GetFly(pUser->GetCharacterInfo().level);
	if (NULL == pFly)
	{
		DEBUGLOG("%s NULL == pFly", __FUNCTION__);
		return;
	}

	if (pFly->_DAMAGES < clsValue.damage_value)
	{
		DEBUGLOG("CHEATUSER %s NULL == pFly GID : %d", __FUNCTION__, pUser->GetUserSeq());
		return;
	}


	if ( (0 == clsValue.ismonster && 0 == clsValue.defender_ismonster)			// 유저가 상대 유저를 공격
			|| (2 == clsValue.ismonster && 0 == clsValue.defender_ismonster)	// 유저의 분신이 상대 유저를 공격
			|| (3 == clsValue.ismonster && 0 == clsValue.defender_ismonster)	// 전투펫이 상대 유저를 공격
			|| (4 == clsValue.ismonster && 0 == clsValue.defender_ismonster) )	// 상대유저에게 도트데미지(출혈, 독 등...)
	{
		NLogic::Space * pSpace	= pUser->GetSpace();
		if (pSpace == NULL)
		{
			DEBUGLOG("CN_ATTACK_DUNGEON::processPVP pSpace is NULL!!!");
			return;
		}

		User * pTarget = NULL;

		DEBUGLOG("%s : PVP Defender=%d, UserSeq=%d", __FUNCTION__, clsValue.defender_gid, pUser->GetUserSeq());

		if (clsValue.defender_gid == static_cast<int>(pUser->GetUserSeq()))
		{
			pTarget = pUser;
			DEBUGLOG("%s : PVP 1 Defender=%d", __FUNCTION__, pTarget->GetUserSeq());
		}
		else
		{
			pTarget = pUser->GetBattle()->GetData()._pvpOppUser;
			DEBUGLOG("%s : PVP 2 Defender=%d", __FUNCTION__, pTarget->GetUserSeq());
		}

		if (pTarget == NULL)
			return;

		NLogic::Status * pStatus = pTarget->GetStatus();
		if (NULL == pStatus)
		{
			DEBUGLOG("%s %d NULL == pStatus", __FUNCTION__, __LINE__);
			return;
		}

		pTarget->GetBattle()->GetData().HP -= clsValue.damage_value;
		if (pTarget->GetBattle()->GetData().HP <= 0)
		{
			pTarget->GetBattle()->GetData().HP = 0;
		}

		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << clsValue.effect;
		*pAck << clsValue.damage_value;
		*pAck << clsValue.defender_gid;
		*pAck << clsValue.defender_ismonster;
		*pAck << pTarget->GetBattle()->GetData().HP;
		*pAck << clsValue.degree;
		*pAck << clsValue.ismonster;
		*pAck << clsValue.attacker_gid;
		*pAck << clsValue.attack_type;

		pAck->MakePacket(CMD_SN_ATTACK_DUNGEON);
		pSpace->SendAll(pAck);

		if (pTarget->GetBattle()->GetData().HP == 0)
		{
			NLogic::Status::Data * pData = pStatus->GetStausData(NLogic::Status::StatusType::BATTLEPET_REBIRTH);
			if (NULL != pData && true == pData->_bRegist)
			{
				DEBUGLOG("BATTLEPET_REBIRTH CMD_SC_REBIRTH_DIRECT BATTLEPET_REBIRTH CALL GID : %d", pTarget->GetUserSeq());

				unsigned int hp = pTarget->GetBattle()->GetData().HP_MAX * pData->_value / 100;
				pTarget->GetBattle()->GetData().HP = hp;

				::Network::Packet * rebirth = ::Network::GETPACKETPOOL()->SEND_NEW();
				* rebirth << static_cast<uint8_t>(0);
				* rebirth << pTarget->GetUserSeq();
				* rebirth << hp;
				rebirth->MakePacket(CMD_SC_REBIRTH_DIRECT);
				pSpace->SendAll(rebirth);

				pData->Clear();
			}
		}

		// PVP 종료
		if (pTarget->GetBattle()->GetData().HP == 0)
		{
			// 타이머 종료
			pSpace->GetParty()->SetState(NLogic::Party::State::PVP_BATTLE_END);

			::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

			int winner	= 0;
			int loser	= 0;

			if (pUser == pTarget)
			{
				winner	= pUser->GetBattle()->GetData()._pvpOppUser->GetUserSeq();
				loser	= pUser->GetUserSeq();
				DEBUGLOG("%s : PVP Winner is Opponent!! Winner=%d, Loser=%d", __FUNCTION__, winner, loser);
			}
			else
			{
				winner	= pUser->GetUserSeq();
				loser	= pTarget->GetUserSeq();
				DEBUGLOG("%s : PVP Winner is Me!! Winner=%d, Loser=%d", __FUNCTION__, winner, loser);
			}


			*pAck << winner;	// 승자
			*pAck << loser;		// 패자

			pAck->MakePacket(CMD_SN_FIGHT_END);
			pSpace->SendAll(pAck);

			pSpace->GetData()._winnerGID = winner;

//			pSpace->GetParty()->EndPVPBattle();
		}
	}
	else
	{
		// 유저가 상대 유저의 분신을 공격
		// 유저가 상대 유저의 전투펫을 공격
		// 유저의 분신이 상대 유저의 분신을 공격
		// 유저의 분신이 상대 유저의 전투펫을 공격
		// 전투펫이 상대 유저의 분신을 공격
		// 전투펫이 상대 유저의 전투펫을 공격

		int targetHP = 0;

		NLogic::Monster * pMonster = pUser->GetSpace()->GetMonster(clsValue.defender_gid);
		if (NULL == pMonster)
		{
			DEBUGLOG("CN_ATTACK_DUNGEON : pMonster is NULL!! monstergid=%d", clsValue.defender_gid);
			return;
		}

		targetHP = pMonster->DecreaseHP(clsValue.damage_value);

		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << clsValue.effect;
		*pAck << clsValue.damage_value;
		*pAck << clsValue.defender_gid;
		*pAck << clsValue.defender_ismonster;
		*pAck << targetHP;
		*pAck << clsValue.degree;
		*pAck << clsValue.ismonster;
		*pAck << clsValue.attacker_gid;
		*pAck << clsValue.attack_type;
		pAck->MakePacket(CMD_SN_ATTACK_DUNGEON);
		pUser->GetSpace()->SendAll(pAck);

		// 몬스터 hp 정보 update 패킷 전송
		::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pNoti << clsValue.defender_gid;
		*pNoti << targetHP;
		pNoti->MakePacket(CMD_SN_DUNGEON_UPDATE_MOB_HP);
		pUser->GetSpace()->SendAll(pNoti);
	}
}

} /*NCombat*/ } /*NProcess*/ } /*ProjectZ*/
